home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / VideoToolbox 94.11.17 / VideoToolboxSources / FlushCacheRange.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-08  |  7.7 KB  |  195 lines  |  [TEXT/KAHL]

  1. /*
  2. FlushCacheRange.c
  3. A machine and system independent cache flush routine.
  4.  
  5. Beginning with the Macintosh II, developers were faced with situations where
  6. instruction and/or data caches needed to be flushed for code to execute
  7. correctly.  Unfortunately, despite recent improvements (i.e. _HWPriv, see Tech
  8. Note #261), cache flushing remains highly CPU- and system-specific and developers
  9. have had difficulty doing it in a way that ensures both forward and backward
  10. compatibility.   FlushCacheRange.c contains a single function call that will work across
  11. all platforms, yet still provides access to such advanced MC68040 features as
  12. selective cache range flushing.
  13.  
  14. Dave Radcliffe Apple DTS January, 1992
  15.  
  16. ****************************************************************************
  17. HISTORY:
  18. 7/92 dgp This routine was distributed by Apple on their Developer Disk for May, 1992.
  19. I changed the name of the file from Cache.c to FlushCacheRange.c, to match the
  20. name of the routine itself, moved the prototype from Cache.h to VideoToolbox.h,
  21. and pasted the contents of the "About..." file above. Otherwise the file is unchanged.
  22.  
  23. 5/28/94 dgp Changed the type of unimpTrapAddress from long to
  24. "UniversalProcPtr" in order to make this file compatible with Apple's Universal Headers.
  25.  
  26. ****************************************************************************
  27.  *
  28.  *    Cache control is a highly CPU specific function.  Although some system independence
  29.  *    is achieved via use of the _HWPriv trap, this solution may not be general for all
  30.  *    hardware/system software combinations.  FlushCacheRange should solve that for
  31.  *    developers by working on all systems.
  32.  *    
  33.  *    Written by:    Dave Radcliffe
  34.  *
  35.  *    Copyright:    © 1991 by Apple Computer, Inc., all rights reserved.
  36.  *
  37.  *    Change History:
  38.  *
  39.  *        1/20/92        DR        Added System603OrLater conditional code
  40.  *        1/10/92        DR        Added FlushCacheWithCPushA()
  41.  *        12/18/91    DR        New today
  42.  *
  43.  */
  44. #if __powerc
  45.     #error "This file cannot yet be compiled as PowerPC native code."
  46. #else
  47.  
  48. #include "VideoToolbox.h"    /* for prototype of FlushCacheRange */
  49.  
  50. #ifndef __TYPES__
  51. #include <Types.h>
  52. #endif
  53.  
  54. #ifndef __TRAPS__
  55. #include <Traps.h>
  56. #endif
  57.  
  58. #ifndef __OSUTILS__
  59. #include <OSUtils.h>
  60. #endif
  61.  
  62. #ifndef __GESTALTEQU__
  63. #include <GestaltEqu.h>
  64. #endif
  65.  
  66. #ifndef __ERRORS__
  67. #include <Errors.h>
  68. #endif
  69.  
  70. /*
  71.  * If you can guarantee you are running on System 6.0.3 or later, then some of the
  72.  * alternative cache flushing code implemented below is unnecessary as you are
  73.  * assured of having the _HWPriv trap.  So, if you are running on System 6.0.3 or
  74.  * later, uncommenting the following line can reduce this code by more than half.
  75.  */
  76. /* #define System603OrLater */
  77.  
  78. /* The next two declarations are defined in Tech Note #261 */
  79. #ifndef FlushCodeCacheRange
  80. /* MPW C 3.1 and earlier, and THINK C should declare the function as   */
  81. /* “pascal” and use the same inline constants as the Pascal interface: */
  82. pascal OSErr FlushCodeCacheRange (void *address, unsigned long count) =
  83.     {0x225F, 0x205F, 0x7009, 0xA198, 0x3E80};
  84.     
  85. /* The above declaration works for MPW C 3.2 as well, but 3.2 allows   */
  86. /* register specifications to make register-based inline calls very    */
  87. /* efficient.  So, under MPW C 3.2, you may choose to uncomment the    */
  88. /* following code, instead.                                            */
  89. /*
  90. #pragma parameter __D0 FlushCodeCacheRange(__A0,__A1)
  91. OSErr FlushCodeCacheRange (void *address, unsigned long count) =
  92.     {0x7009, 0xA198};
  93. */
  94. #endif
  95.  
  96. #ifndef FlushCodeCache
  97. #define _CacheFlush 0xA0BD
  98. void FlushCodeCache (void) = _CacheFlush;
  99. #endif
  100.  
  101. /* 
  102.  * FlushCacheViaCACR is an inline assembly routine that flushes both the 
  103.  * instruction and data caches by writing directly to the CACR.  Used only
  104.  * as a last resort by FlushCacheRange
  105.  */
  106. void FlushCacheViaCACR ( void ) =
  107.     { 0x4E7A, 0x0002,        /* MOVEC    CACR,D0 */
  108.       0x08C0, 0x0003,        /* BSET        #3,D0   */
  109.       0x4E7B, 0x0002 };        /* MOVEC    D0,CACR */
  110.  
  111. /*
  112.  * FlushCacheWithCPushA is another inline assembly routine that flushes caches
  113.  * on the MC68040 using the CPushA instruction.  Used only as a last resort
  114.  * by FlushCacheRange
  115.  */
  116. void FlushCacheWithCPushA ( void ) =
  117.     { 0x4E71,                /* NOP, to clear pending writes */
  118.       0xF4F8 };                /* CPUSHA    BC */
  119.       
  120. /*
  121.  * FlushCacheRange flushes both the data and instruction caches for the block of 
  122.  * memory starting at location address with size count.  Flushing the cache for 
  123.  * a range of memory is only supported on the 68040, so if this functionality is
  124.  * unavailable, the entire cache is flushed (if appropriate).
  125.  *
  126.  * If either address is NIL or count is zero, the entire cache is flushed anyway.
  127.  * Selective flushing of the cache is a time consuming process and you may wish to
  128.  * avoid it when there is no benefit to doing so.  For example, if you've recently
  129.  * manipulated a block larger than 4K (the size of the 68040 caches), selective
  130.  * flushing will probably end up flushing the entire cache anyway, so why bother?
  131.  *
  132.  * The preferred method for flushing the cache is to use the _HWPriv trap documented
  133.  * in Tech Note #261.  Some older systems may not have this trap implemented, so
  134.  * alternate methods must be used.  The first thing to try is the _CacheFlush trap.
  135.  * This was implemented beginning with the Mac II (and is also documented in Tech
  136.  * Note #261).
  137.  *
  138.  * MC68000 based systems have no cache, but if an accelerator board has been added.
  139.  * they may have a CPU which does have a cache.  Accelerator board vendors should
  140.  * implement _HWPriv or _CacheFlush for such systems, but if they haven't then
  141.  * our last resort is to control the caches directly (using privileged
  142.  * instructions (GAK!!)).
  143.  *
  144.  * FINALLY, the full implementation of FlushCacheRange is probably overkill and may be 
  145.  * less than optimal for some applications.  For example, testing for _HWPriv 
  146.  * should be unnecessary on systems later than 6.0.2, so I've added conditional code
  147.  * to allow you to bypass that if appropriate (see comment above on System603OrLater).
  148.  * The full implementation tries to cover a lot of obscure cases, but it also does 
  149.  * some things inefficiently.  For example, having determined that _HWPriv is 
  150.  * implemented, it would be more efficient to just keep that information around, 
  151.  * but I wanted to avoid the complications of global or static variables.  But 
  152.  * it is also true that if you find it necessary to call this code more than a
  153.  * few times between the time your application starts and the time it quits, 
  154.  * YOU ARE DOING SOMETHING WRONG!!   Go back and rethink your code.
  155.  */
  156. void FlushCacheRange (void *address, unsigned long count)
  157. {
  158. #ifndef System603OrLater
  159.     long    gestaltResponse;            /* For CPU type */
  160.     #if defined(USESROUTINEDESCRIPTORS)
  161.         UniversalProcPtr unimpTrapAddress;    /* Address of Unimplemented Trap */
  162.     #else
  163.         long unimpTrapAddress;            /* Address of Unimplemented Trap */
  164.     #endif    
  165.  
  166.     /* First check to see if _HWPriv is implemented */
  167.     if ((unimpTrapAddress = NGetTrapAddress(_Unimplemented, ToolTrap)) != 
  168.         NGetTrapAddress(_HWPriv, OSTrap)) {
  169. #endif
  170.         /* 
  171.          * Try to flush the specified range.  If it fails or if there is no range,
  172.          * then flush the entire cache 
  173.          */
  174.         if (!(address && count && (FlushCodeCacheRange (address, count) != hwParamErr))) {    
  175.             /* Flush entire cache */
  176.             FlushInstructionCache ();
  177.         }
  178. #ifndef System603OrLater
  179.     } else {                /* No _HWPriv trap */
  180.         /* Try for _CacheFlush trap */
  181.         if (unimpTrapAddress != NGetTrapAddress(_CacheFlush, OSTrap))
  182.             FlushCodeCache ();
  183.         else        /* Nothing else works, so do machine specific cache control */
  184.             /* Only bother with cache control on 68020 and above */
  185.             if (!Gestalt (gestaltProcessorType, &gestaltResponse) && 
  186.                 (gestaltResponse >= gestalt68020))
  187.                     if (gestaltResponse <= gestalt68030)
  188.                         FlushCacheViaCACR ();
  189.                     else
  190.                         FlushCacheWithCPushA ();
  191.     }
  192. #endif
  193.     return;
  194. }    /* FlushCacheRange */
  195. #endif